"""
视频处理任务
"""
import os
import uuid
import logging
import tempfile
from datetime import datetime
from celery import Celery
from sqlalchemy.orm import Session
from app.db.session import SessionLocal
from app.models.video_task import VideoTask
from app.core.content_analyzer import ContentAnalyzer
from app.core.decision_engine import DecisionEngine
from app.core.video_generator import VideoGenerator
from app.core.storage.storage_manager import StorageManager
from app.config import settings
from app.exceptions import VideoProcessingError

# 创建Celery实例
celery_app = Celery(
    "video_tasks",
    broker=settings.CELERY_BROKER_URL,
    backend=settings.CELERY_RESULT_BACKEND
)

# Celery配置
celery_app.conf.update(
    task_serializer=settings.CELERY_TASK_SERIALIZER,
    accept_content=settings.CELERY_ACCEPT_CONTENT,
    result_serializer=settings.CELERY_RESULT_SERIALIZER,
    timezone=settings.CELERY_TIMEZONE,
    enable_utc=True,
    task_track_started=True,
    task_time_limit=settings.VIDEO_PROCESSING_TIMEOUT,
    task_soft_time_limit=settings.VIDEO_PROCESSING_TIMEOUT - 60,
    worker_prefetch_multiplier=1,
    worker_max_tasks_per_child=1000,
)

logger = logging.getLogger(__name__)


@celery_app.task(bind=True)
def process_video_task(self, task_id: str):
    """
    处理视频任务的主函数

    Args:
        task_id: 任务ID
    """
    db = SessionLocal()
    start_time = datetime.utcnow()

    try:
        # 获取任务记录
        video_task = db.query(VideoTask).filter(VideoTask.id == task_id).first()
        if not video_task:
            raise VideoProcessingError(f"任务不存在: {task_id}")

        # 更新任务状态为处理中
        video_task.status = "processing"
        video_task.started_at = start_time
        video_task.current_step = "初始化处理流程"
        video_task.progress = 0.0
        db.commit()

        # 更新任务进度
        self.update_state(
            state="PROCESSING",
            meta={
                "status": "processing",
                "progress": 0,
                "current_step": "初始化处理流程"
            }
        )

        logger.info(f"Starting video processing for task {task_id}")

        # 初始化处理组件
        content_analyzer = ContentAnalyzer()
        decision_engine = DecisionEngine()
        video_generator = VideoGenerator()
        storage_manager = StorageManager()

        def progress_callback(step: str, progress: float):
            """进度回调函数"""
            video_task.current_step = step
            video_task.progress = progress
            db.commit()

            # 更新Celery任务状态
            self.update_state(
                state="PROCESSING",
                meta={
                    "status": "processing",
                    "progress": progress,
                    "current_step": step
                }
            )

            logger.info(f"Task {task_id}: {step} - {progress}%")

        # 步骤1: 下载原始视频
        progress_callback("下载原始视频", 5)
        original_video_path = await storage_manager.download_file(video_task.original_file_url)

        # 步骤2: 视频内容分析
        progress_callback("分析视频内容", 10)
        analysis_result = await content_analyzer.analyze_video(
            original_video_path, progress_callback
        )

        # 保存分析结果
        video_task.transcription_data = analysis_result.get("transcription")
        video_task.analysis_data = analysis_result.get("text_analysis")
        video_task.duration = analysis_result["video_info"]["duration"]
        video_task.format = analysis_result["video_info"].get("format")
        db.commit()

        # 步骤3: 生成剪辑决策
        progress_callback("生成剪辑决策", 70)
        editing_decision = await decision_engine.generate_editing_decision(
            analysis_result["semantic_units"],
            video_task.target_platform,
            video_task.duration,
            progress_callback
        )

        # 保存剪辑片段信息
        video_task.cut_segments = editing_decision["segments"]
        video_task.template_config = editing_decision["template_config"]
        db.commit()

        # 步骤4: 生成最终视频
        progress_callback("生成最终视频", 75)
        output_filename = f"{video_task.title}_{video_task.target_platform}_{task_id}.mp4"
        output_path = f"videos/processed/{task_id}/{output_filename}"

        # 生成视频文件
        generation_result = await video_generator.generate_video(
            original_video_path,
            editing_decision,
            output_path,
            progress_callback
        )

        # 上传生成的视频到存储
        progress_callback("上传输出视频", 95)
        with open(generation_result["output_path"], "rb") as f:
            output_video_url = await storage_manager.upload_file(
                content=f.read(),
                file_path=output_path,
                content_type="video/mp4"
            )

        # 上传缩略图
        thumbnail_url = None
        if generation_result["thumbnail_path"]:
            thumbnail_filename = f"thumbnail_{task_id}.jpg"
            thumbnail_path = f"videos/thumbnails/{task_id}/{thumbnail_filename}"
            with open(generation_result["thumbnail_path"], "rb") as f:
                thumbnail_url = await storage_manager.upload_file(
                    content=f.read(),
                    file_path=thumbnail_path,
                    content_type="image/jpeg"
                )

        # 步骤5: 完成任务
        end_time = datetime.utcnow()
        processing_time = (end_time - start_time).total_seconds()

        # 更新任务记录
        video_task.status = "completed"
        video_task.progress = 100.0
        video_task.current_step = "处理完成"
        video_task.completed_at = end_time
        video_task.processing_time = processing_time
        video_task.output_video_url = output_video_url
        video_task.thumbnail_url = thumbnail_url
        db.commit()

        # 清理临时文件
        try:
            if os.path.exists(original_video_path):
                os.remove(original_video_path)
            if os.path.exists(generation_result["output_path"]):
                os.remove(generation_result["output_path"])
            if generation_result["thumbnail_path"] and os.path.exists(generation_result["thumbnail_path"]):
                os.remove(generation_result["thumbnail_path"])
        except Exception as e:
            logger.warning(f"Failed to clean up temporary files: {e}")

        logger.info(f"Video processing completed successfully for task {task_id}")

        # 返回结果
        return {
            "status": "completed",
            "task_id": task_id,
            "output_video_url": output_video_url,
            "thumbnail_url": thumbnail_url,
            "processing_time": processing_time,
            "duration": video_task.duration,
            "segments_count": len(editing_decision["segments"])
        }

    except Exception as e:
        logger.error(f"Video processing failed for task {task_id}: {e}", exc_info=True)

        # 更新任务状态为失败
        try:
            video_task.status = "failed"
            video_task.current_step = "处理失败"
            video_task.error_message = str(e)
            video_task.error_details = {
                "error_type": type(e).__name__,
                "error_message": str(e),
                "processing_time": (datetime.utcnow() - start_time).total_seconds()
            }
            db.commit()
        except Exception as db_error:
            logger.error(f"Failed to update task status in database: {db_error}")

        # 清理临时文件
        try:
            if 'original_video_path' in locals() and os.path.exists(original_video_path):
                os.remove(original_video_path)
        except Exception as cleanup_error:
            logger.warning(f"Failed to clean up temporary files: {cleanup_error}")

        # 重新抛出异常，让Celery记录任务失败
        raise VideoProcessingError(f"视频处理失败: {e}")

    finally:
        db.close()


@celery_app.task
def cleanup_old_videos():
    """清理旧的临时文件和过期任务"""
    db = SessionLocal()
    try:
        # 查找超过30天的已完成任务
        from datetime import timedelta
        cutoff_date = datetime.utcnow() - timedelta(days=30)

        old_tasks = db.query(VideoTask).filter(
            VideoTask.status == "completed",
            VideoTask.completed_at < cutoff_date
        ).all()

        storage_manager = StorageManager()
        deleted_count = 0

        for task in old_tasks:
            try:
                # 删除存储中的文件
                if task.original_file_url:
                    await storage_manager.delete_file(task.original_file_url)
                if task.output_video_url:
                    await storage_manager.delete_file(task.output_video_url)
                if task.thumbnail_url:
                    await storage_manager.delete_file(task.thumbnail_url)

                # 删除数据库记录
                db.delete(task)
                deleted_count += 1

            except Exception as e:
                logger.warning(f"Failed to cleanup task {task.id}: {e}")

        db.commit()
        logger.info(f"Cleanup completed: {deleted_count} old tasks deleted")

        return {"deleted_count": deleted_count}

    except Exception as e:
        logger.error(f"Cleanup failed: {e}")
        raise
    finally:
        db.close()


# 定期任务配置
@celery_app.on_after_configure.connect
def setup_periodic_tasks(sender, **kwargs):
    """设置定期任务"""
    # 每天凌晨2点清理旧文件
    sender.add_periodic_task(
        crontab(hour=2, minute=0),
        cleanup_old_videos.s(),
        name='cleanup-old-videos'
    )